package com.example.controller;

import com.example.Service.AccountDetailsService;
import com.example.Service.AccountPrivacyService;
import com.example.Service.AccountService;
import com.example.entity.RestBean;
import com.example.entity.dto.Account;
import com.example.entity.dto.AccountDetails;
import com.example.entity.vo.redponse.AccountDetailsVO;
import com.example.entity.vo.redponse.AccountPrivacyVO;
import com.example.entity.vo.redponse.AccountVO;
import com.example.entity.vo.request.ChangPasswordVO;
import com.example.entity.vo.request.DetailsSaveVO;
import com.example.entity.vo.request.ModifyEmailVO;
import com.example.entity.vo.request.PrivacySaveVO;
import com.example.utils.Const;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;
import java.util.function.Supplier;

/**
 * 作者:xuSen
 * 日期2025/4/22 15:10
 */
// 控制器类，处理与用户账户相关的API请求
@RestController
@Slf4j
@RequestMapping("/api/user")
public class AccountController {
    // 注入Account服务，用于处理账户相关的业务逻辑
    @Resource
    private AccountService accountService;
    // 注入AccountDetails服务，用于处理账户详细信息相关的业务逻辑
    @Resource
    private AccountDetailsService accountDetailsService;
    @Resource
    private AccountPrivacyService accountPrivacyService;

    /**
     * 获取用户账户信息
     *
     * 通过用户ID获取账户详细信息此方法假设调用前已经通过某种方式（如登录认证）获取到用户ID，
     * 并将其作为请求属性(RequestAttribute)传递过来
     *
     * @param id 用户ID，从请求属性中获取，用于识别特定的用户账户
     * @return 包含账户信息的RestBean对象，以JSON形式返回给客户端
     */
    @GetMapping("/info")
    public RestBean<AccountVO> info(@RequestAttribute(Const.ATTR_USER_ID) int id){
        // 根据用户ID查询账户信息，并将结果转换为AccountVO对象返回
        Account account=accountService.findAccountById(id);
        return RestBean.success(account.asViewObject(AccountVO.class));
    }

    /**
     * 获取用户账户详细信息
     *
     * 通过用户ID获取账户的详细信息，此方法同样假设用户ID已经作为请求属性传递过来
     * 如果未找到对应的账户详细信息，则创建一个新的AccountDetails对象
     *
     * @param id 用户ID，从请求属性中获取，用于识别特定的用户账户
     * @return 包含账户详细信息的RestBean对象，以JSON形式返回给客户端
     */
    @GetMapping("/details")
    public RestBean<AccountDetailsVO> details(@RequestAttribute(Const.ATTR_USER_ID) int id){
        AccountDetails accountDetails = Optional
                .ofNullable(accountDetailsService.findAccountDetailsById(id))
                .orElseGet(AccountDetails::new);
        return RestBean.success(accountDetails.asViewObject(AccountDetailsVO.class));
    }

    /**
     * 保存用户账户详细信息
     *
     * 接收用户ID和账户详细信息对象，尝试更新数据库中的账户详细信息
     * 如果保存成功，返回成功信息；如果失败（例如用户名重复），则返回错误信息
     *
     * @param id 用户ID，从请求属性中获取，用于识别特定的用户账户
     * @param vo 包含要保存的账户详细信息的对象，通过请求体传递
     * @return 表示保存操作结果的RestBean对象，以JSON形式返回给客户端
     */
    @PostMapping("/save-details")
    public RestBean<Void> saveDetails(@RequestAttribute(Const.ATTR_USER_ID) int id,
                                      @RequestBody @Valid DetailsSaveVO vo){
        boolean success = accountDetailsService.saveAccountDetails(id, vo);
        return success?RestBean.success():RestBean.failure(400,"此用户名已经被其他用户使用，请重新更换");
    }

    /**
     * 修改用户邮箱
     *
     * 接收用户ID和新的邮箱信息，尝试更新用户的邮箱地址
     * 如果修改成功，返回成功信息；如果失败（例如邮箱已被使用），则返回错误信息
     *
     * @param id 用户ID，从请求属性中获取，用于识别特定的用户账户
     * @param vo 包含新邮箱信息的对象，通过请求体传递
     * @return 表示修改操作结果的RestBean对象，以JSON形式返回给客户端
     */
    @PostMapping("/modify-email")
    public RestBean<Void> modifyEmail(@RequestAttribute(Const.ATTR_USER_ID) int id,
                                      @RequestBody @Valid ModifyEmailVO vo){
        String s = accountService.modifyEmail(id, vo);
        return s==null?RestBean.success():RestBean.failure(400,s);
    }
    /**
     * 处理更改密码请求
     * 此方法接收用户ID和新密码信息，调用服务层方法为用户更改密码
     *
     * @param id 用户ID，用于标识需要更改密码的用户
     * @param vo 包含新密码信息的ChangPasswordVO对象，用于接收客户端提交的新密码数据
     * @return RestBean<Void> 返回一个表示操作结果的RestBean对象，包含操作成功或失败的信息
     */
    @PostMapping("/change-password")
    public RestBean<Void> changePassword(@RequestAttribute(Const.ATTR_USER_ID) int id,
                                         @RequestBody @Valid ChangPasswordVO vo) {
        // 调用服务层方法更改用户密码，并接收更改结果
//        String s = accountService.changePassword(id,vo);
        // 根据更改结果返回成功或失败的响应
//        return s==null?RestBean.success():RestBean.failure(400,s);
        // 简化代码
        return this.messageHandle(() -> accountService.changePassword(id, vo));
    }
    /**
     * 保存用户隐私设置的接口
     * 该方法处理POST请求，请求路径为/save-privacy
     * 使用RequestAttribute注解从HTTP请求中提取用户ID，使用RequestBody注解获取请求体中的数据
     * 参数vo被验证注解标记，以确保传入的数据符合规范
     *
     * @param id 用户ID，用于标识哪个用户的隐私设置需要保存
     * @param vo 包含用户隐私设置信息的对象，经过验证确保数据的合法性
     * @return 返回一个表示操作成功的RestBean对象，不包含具体数据
     */
    @PostMapping("/save-privacy")
    public RestBean<Void> savePrivacy(@RequestAttribute(Const.ATTR_USER_ID) int id,
                                      @RequestBody @Valid PrivacySaveVO vo) {
        // 简化代码
        accountPrivacyService.savePrivacy(id, vo);
        return RestBean.success();
    }
    /**
     * 处理获取用户隐私设置的GET请求
     * 该方法通过用户ID获取用户的隐私设置，并以AccountPrivacyVO对象的形式返回
     *
     * @param id 用户ID，通过RequestAttribute注解从请求中获取
     * @return 包含用户隐私设置的RestBean对象
     */
    @GetMapping("/privacy")
    public RestBean<AccountPrivacyVO> Privacy(@RequestAttribute(Const.ATTR_USER_ID) int id) {

        // 调用服务层方法获取用户隐私设置，并转换为AccountPrivacyVO对象返回
        return RestBean.success(accountPrivacyService.accountPrivacy(id).asViewObject(AccountPrivacyVO.class));
    }
    /**
     * 针对于返回值为String作为错误信息的方法进行统一处理
     *
     * @param action 具体操作
     * @param <T>    响应结果类型
     * @return 响应结果
     */
    private <T> RestBean<T> messageHandle(Supplier<String> action) {
        // 执行具体操作并获取结果消息
        String message = action.get();
        // 如果消息为空，则表示操作成功，返回成功响应
        if (message == null)
            return RestBean.success();
            // 否则，表示操作失败，返回包含错误消息的失败响应
        else
            return RestBean.failure(400, message);
    }
}























